Method and system for naming and binding objects

ABSTRACT

A method and system for referring to and binding to objects using a moniker object is provided. In preferred embodiments a moniker object contains information to identify linked source data and provides methods through which a program can bind to the linked source data. A binding method is provided that returns an instance of an interface through which the linked source data can be accessed. In a preferred embodiment, the moniker object provides other methods including a reducing method that returns a more efficient representation of the moniker object; equality and hash methods for comparing moniker objects; and inverse, common prefix, and relative-path-to methods for comparing and locating moniker objects from other moniker objects. Several implementations of a moniker object are provided. Each implementation is a moniker class and has a class identifier that identifies code to manage the moniker class.

This application is a continuation-in-part of U.S. Ser. No. 07/909,983,filed Jul. 6, 1992, now pending.

TECHNICAL FIELD

This invention relates generally to a computer method and system forreferencing objects and, more specifically, to a method and system fornaming objects and binding to objects

BACKGROUND OF THE INVENTION

Current document processing computer systems allow a user to preparecompound documents. A compound document is a document that containsinformation in various formats. For example, a compound document maycontain data in text format, chart format, numerical format, etc. FIG. 1is an example of a compound document. In this example, the compounddocument 101 is generated as a report for a certain manufacturingproject. The compound document 101 contains scheduling data 102, whichis presented in chart format; budgeting data 103, which is presented inspreadsheet format; and explanatory data 104, which is presented in textformat. In typical prior systems, a user generates the scheduling data102 using a project management computer program and the budgeting data103 using a spreadsheet computer program. After this data has beengenerated, the user creates the compound document 101, enters theexplanatory data 104, and incorporates the scheduling data 102 andbudgeting data 103 using a word processing computer program.

FIG. 2 shows a method for incorporating the scheduling data, budgetingdata, and explanatory data into the compound document. A user generatesscheduling data using the project management program 201 and then storesthe data in the clipboard 203. The user also generates budgeting datausing the spreadsheet program 204 and then stores the data in theclipboard 203. The clipboard 203 is an area of storage (disk or memory)that is typically accessible by any program and is used to transfer databetween programs. The project management program 201 and the spreadsheetprogram 204 typically store the data into the clipboard in apresentation format. A presentation format is a format in which the datais easily displayed on an output device. For example, the presentationformat may be a bitmap that can be displayed with a standard bitmapblock transfer operation (BitBlt). The storing of data into a clipboardis referred to as “copying” to the clipboard.

After data has been copied to the clipboard 203, the user starts up theword processing program 206 to create the compound document 101. Theuser enters the explanatory data 104 and specifies the locations in thecompound document 101 to which the scheduling data and budgeting datathat are in the clipboard 203 are to be copied. The copying of data froma clipboard to a document is referred to as “pasting” from theclipboard. The word processing program 206 then copies the schedulingdata 102 and the budgeting data 103 from the clipboard 203 into thecompound document 101 at the specified locations. Data that is copiedfrom the clipboard into a compound document is referred to as “embedded”data. The word processing program 206 treats the embedded data as simplebitmaps that it displays with a BitBlt operation when rendering thecompound document 101 on an output device. In some prior systems, aclipboard may only be able to store data for one copy command at a time.In such a system, the scheduling data can be copied to the clipboard andthen pasted into the compound document. Then, the budgeting data can becopied to the clipboard and then pasted into the compound document.

Since word processors typically process only text data, users of theword processing program can move or delete embedded data, but cannotmodify embedded data, unless the data is in text format. Thus, if a userwants to modify, for example, the budgeting data 103 that is in thecompound document 101, the user must start up the spreadsheet program204, load in the budgeting data 103 from a file, make the modifications,copy the modifications to the clipboard 203, start up the wordprocessing program 206, load in the compound document 101, and paste themodified clipboard data into the compound document 101.

Some prior systems store links to the data to be included in thecompound document rather than actually embedding the data. When a wordprocessing program pastes the data from a clipboard into a compounddocument, a link is stored in the compound document. The link points tothe data (typically residing in a file) to be included. These priorsystems typically provide links to data in a format that the wordprocessing program recognizes or treats as presentation format. Forexample, when the word processing program 206 is directed by a user topaste the scheduling data and budgeting data into the compound documentby linking, rather than embedding, the names of files in which thescheduling data and budgeting data reside in presentation format areinserted into the document. Several compound documents can contain linksto the same data to allow one copy of the data to be shared by severalcompound documents.

A link is conceptually a path name to the data. Some prior systems storetwo-level links. A two-level link identifies both a file and an areawithin the file. For example, the two-level link “\BUDGET.XLS\R2C2:R7C4”identifies a spreadsheet file “\BUDGET.XLS” and the range of cells“R2C2:R7C4.” The use of two-level links limits the source of the linksto data that is nested one level within a file. If a file containsmultiple spreadsheets, then a two-level link could identify the file anda spreadsheet, but could not identify a range within the spreadsheet. Itwould be desirable to have a method and system of supporting links to anarbitrary level.

Since the present invention is described below using object-orientedprogramming, an overview of well-known object-oriented programmingtechniques is provided. Two common characteristics of object-orientedprogramming languages are support for data encapsulation and data typeinheritance. Data encapsulation refers to the binding of functions anddata. Inheritance refers to the ability to declare a data type in termsof other data types.

In the C++ language, object-oriented techniques are supported throughthe use of classes. A class is a user-defined type. A class declarationdescribes the data members and function members of the class. Forexample, the following declaration defines data members and a functionmember of a class named CIRCLE. class CIRCLE { public: int x, y; intradius; void draw( ); };Variables x and y specify the center location of a circle and variableradius specifies the radius of the circle. These variables are referredto as data members of the class CIRCLE. The function draw is auser-defined function that draws the circle of the specified radius atthe specified location. The function draw is referred to as a functionmember of class CIRCLE. The data members and function members of a classare bound together in that the function operates on an instance of theclass. An instance of a class is also called an object of the class.

In the syntax of C++, the following statement declares the objects a andb to be of type class CIRCLE.

CIRCLE a, b;

This declaration causes the allocation of memory for the objects a andb. The following statements assign data to the data members of objects aand b.

a.x=2;

a.y=2;

a.radius=1;

b.x=4;

b.y=5;

b.radius=2;

The following statements are used to draw the circles defined by objectsa and b.

a.draw( );

b.draw( );

A derived class is a class that inherits the characteristics—datamembers and function members—of its base classes. For example, thefollowing derived class CIRCLE_FILL inherits the characteristics of thebase class CIRCLE. class CIRCLE_FILL : CIRCLE { public: int pattern;void fill( ); };This declaration specifies that class CIRCLE_FILL includes all the dataand function members that are in class CIRCLE in addition to those dataand function members introduced in the declaration of class CIRCLE_FILL,that is, data member pattern and function member fill. In this example,class CIRCLE_FILL has data members x, y, radius, and pattern andfunction members draw and fill. Class CIRCLE_FILL is said to “inherit”the characteristics of class CIRCLE. A class that inherits thecharacteristics of another class is a derived class (e.g., CIRCLE_FILL).A class that does not inherit the characteristics of another class is aprimary (root) class (e.g., CIRCLE). A class whose characteristics areinherited by another class is a base class (e.g., CIRCLE is a base classof CIRCLE_FILL). A derived class may inherit the characteristics ofseveral classes, that is, a derived class may have several base classes.This is referred to as multiple inheritance.

A derived class may specify that a base class is to be inheritedvirtually. Virtual inheritance of a base class means that only oneinstance of the virtual base class exists in the derived class. Forexample, the following is an example of a derived class with twononvirtual base classes.

class CIRCLE_(—)1 : CIRCLE { . . . };

class CIRCLE_(—)2 : CIRCLE { . . . };

class PATTERN : CIRCLE_(—)1, CIRCLE_(—)2{ . . . };

In this declaration class PATTERN inherits class CIRCLE twicenonvirtually through classes CIRCLE_(—)1 and CIRCLE_(—)2. There are twoinstances of class CIRCLE in class PATTERN.

The following is an example of a derived class with two virtual baseclasses.

class CIRCLE_(—)1 : virtual CIRCLE { . . . };

class CIRCLE_(—)2 : virtual CIRCLE { . . . };

class PATTERN: CIRCLE_(—)1, CIRCLE_(—)2{ . . . };

The derived class PATTERN inherits class CIRCLE twice virtually throughclasses CIRCLE_(—)1 and CIRCLE_(—)2. Since the class CIRCLE is virtuallyinherited twice, there is only one object of class CIRCLE in the derivedclass PATTERN. One skilled in the art would appreciate virtualinheritance can be very useful when the class derivation is morecomplex.

A class may also specify whether its function members are virtual.Declaring that a function member is virtual means that the function canbe overridden by a function of the same name and type in a derivedclass. In the following example, the function draw is declared to bevirtual in classes CIRCLE and CIRCLE_FILL. class CIRCLE { public: int x,y; int radius; virtual void draw( ); }; class CIRCLE_FILL : CIRCLE {public: int pattern; virtual void draw( ); };

The C++ language provides a pointer data type. A pointer holds valuesthat are addresses of objects in memory. Through a pointer, an objectcan be referenced. The following statement declares variable c_ptr to bea pointer on an object of type class CIRCLE and sets variable c_ptr tohold the address of object c.

CIRCLE *c_ptr;

c_ptr=&c;

Continuing with the example, the following statement declares object ato be of type class CIRCLE and object b to be of type class CIRCLE_FILL.

CIRCLE a;

CIRCLE_FILL b;

The following statement refers to the function draw as defined in classCIRCLE.

a.draw( );

Whereas, the following statement refers to the function draw defined inclass CIRCLE_FILL.

b.draw( );

Moreover, the following statements type cast object b to an object oftype class CIRCLE and invoke the function draw that is defined in classCIRCLE_FILL. CIRCLE *c_ptr; c_ptr = &b; c_ptr−>draw( ); //CIRCLE_FILL::draw( )Thus, the virtual function that is called is function CIRCLE_FILL::draw.

FIG. 3 is a block diagram illustrating typical data structures used torepresent an object. An object is composed of instance data (datamembers) and member functions, which implement the behavior of theobject. The data structures used to represent an object compriseinstance data structure 301, virtual function table 302, and thefunction members 303, 304, 305. The instance data structure 301 containsa pointer to the virtual function table 302 and contains data members.The virtual function table 302 contains an entry for each virtualfunction member defined for the object. Each entry contains a referenceto the code that implements the corresponding function member. Thelayout of this sample object conforms to the model defined in U.S.patent application Ser. No. 07/682,537, entitled “A Method forImplementing Virtual Functions and Virtual Bases in a Compiler for anObject Oriented Programming Language,” which is hereby incorporated byreference. In the following, an object will be described as an instanceof a class as defined by the C++ programming language. One skilled inthe art would appreciate that objects can be defined using otherprogramming languages.

An advantage of using object-oriented techniques is that thesetechniques can be used to facilitate the sharing of objects. Inparticular, object-oriented techniques facilitate the creation ofcompound documents. A compound document (as described above) is adocument that contains objects generated by various computer programs.(Typically, only the data members of the object and the class type arestored in a compound document.) For example, a word processing documentthat contains a spreadsheet object generated by a spreadsheet program isa compound document. A word processing program allows a user to embed aspreadsheet object (e.g., a cell) within a word processing document. Toallow this embedding, the word processing program is compiled using theclass definition of the object to be embedded to access function membersof the embedded object. Thus, the word processing program would need tobe compiled using the class definition of each class of objects that canbe embedded in a word processing document. To embed an object of a newclass into a word processing document, the word processing program wouldneed to be recompiled with the new class definition. Thus, only objectsof classes selected by the developer of the word processing program canbe embedded. Furthermore, new classes can only be supported with a newrelease of the word processing program.

To allow objects of an arbitrary class to be embedded into compounddocuments, interfaces are defined through which an object can beaccessed without the need for the word processing program to have accessto the class definitions at compile time. An abstract class is a classin which a virtual function member has no implementation (pure). Aninterface is an abstract class with no data members and whose virtualfunctions are all pure.

The following class definition is an example definition of an interface.In this example, for simplicity of explanation, rather than allowing anyclass of object to be embedded in its documents, a word processingprogram allows spreadsheet objects to be embedded. Any spreadsheetobject that provides this interface can be embedded, regardless of howthe object is implemented. Moreover, any spreadsheet object, whetherimplemented before or after the word processing program is compiled, canbe embedded. class ISpreadSheet { virtual void File( ) = 0; virtual voidEdit( ) = 0; virtual void Formula( ) = 0; virtual void Format( ) = 0;virtual void GetCell (string RC, cell *pCell) = 0; virtual void Data( )= 0; }The developer of a spreadsheet program would need to provide animplementation of the interface to allow the spreadsheet objects to beembedded in a word processing document. When the word processing programembeds a spreadsheet object, the program needs access to the code thatimplements the interface for the spreadsheet object. To access the code,each implementation is given a unique class identifier. For example, aspreadsheet object developed by Microsoft Corporation may have a classidentifier of “MSSpreadsheet,” while a spreadsheet object developed byanother corporation may have a class identifier of “LTSSpreadsheet.” Apersistent registry in each computer system is maintained that maps eachclass identifier to the code that implements the class. Typically, whena spreadsheet program is installed on a computer system, the persistentregistry is updated to reflect the availability of that class ofspreadsheet objects. So long as a spreadsheet developer implements eachfunction member defined by the interface and the persistent registry ismaintained, the word processing program can embed the developer'sspreadsheet objects into a word processing document.

Various spreadsheet developers may wish, however, to implement onlycertain function members. For example, a spreadsheet developer may notwant to implement database support, but may want to support all otherfunction members. To allow a spreadsheet developer to support only someof the function members, while still allowing the objects to beembedded, multiple interfaces for spreadsheet object are defined. Forexample, the interfaces IDatabase and IBasic may be defined for aspreadsheet object as follows. class IBasic { virtual void File( ) = 0;virtual void Edit( ) = 0; virtual void Formula( ) = 0; virtual voidFormat( ) = 0; virtual void GetCell (string RC, cell *pCell) = 0; }class IDatabase { virtual void Data( ) = 0; }Each spreadsheet developer would implement the IBasic interface and,optionally, the IDatabase interface.

At run time, the word processing program would need to determine whethera spreadsheet object to be embedded supports the IDatabase interface. Tomake this determination, another interface is defined (that everyspreadsheet object implements) with a function member that indicateswhich interfaces are implemented for the object. This interface is namedIUnknown (and referred to as the unknown interface or the objectmanagement interface) and is defined as follows. class IUnknown {virtual HRESULT QueryInterface (REFIID iid, void **ppv) = 0; virtualULONG AddRef( ) = 0; virtual ULONG Release ( ) = 0; }

The IUnknown interface defines the function member (method)QueryInterface. The method QueryInterface is passed an interfaceidentifier (e.g., “IDatabase”) in parameter iid (of type REFIID) andreturns a pointer to the implementation of the identified interface forthe object for which the method is invoked in parameter ppv. If theobject does not support the interface, then the method returns a false.(The type HRESULT indicates a predefined status, and the type ULONGindicates an unsigned long integer.) CODE TABLE 1 HRESULTXX::QueryInterface(REFIID iid, void **ppv) { ret = TRUE; switch (iid) {case IID_IBasic: *ppv = *pIBasic; break; case IID_IDatabase: *ppv =*pIDatabase; break; case IID_IUnknown: *ppv = this; break; default: ret= FALSE; } if (ret == TRUE){AddRef( );}; return ret; }

Code Table 1 contains C++ pseudocode for a typical implementation of themethod QueryInterface for class XX, which inherits the class IUnknown.If the spreadsheet object supports the IDatabase interface, then themethod QueryInterface includes the appropriate case label within theswitch statement. The variables pIbasic and pIDatabase point to apointer to the virtual function tables of the Ibasic and IDatabaseinterfaces, respectively. The method QueryInterface invokes the methodAddRef (described below) to increment a reference count for the objectof class XX when a pointer to an interface is returned. CODE TABLE 2void XX::AddRef( ) {refcount++;} void XX::Release( ) {if (−−refcount==0)delete this;}

The interface IUnknown also defines the methods AddRef and Release,which are used to implement reference counting. Whenever a new referenceto an interface is created, the method AddRef is invoked to increment areference count of the object. Whenever a reference is no longer needed,the method Release is invoked to decrement the reference count of theobject and, when the reference count goes to zero, to deallocate theobject. Code Table 2 contains C++ pseudocode for a typicalimplementation of the methods AddRef and Release for class XX, whichinherits the class IUnknown.

The IDatabase interface and IBasic interface inherit the IUnknowninterface. The following definitions illustrate the use of the IUnknowninterface. class IDatabase : public IUnknown { public: virtual voidData( ) = 0; } class IBasic : public IUnknown { public:  virtual voidFile( ) = 0; virtual void Edit( ) = 0; virtual void Formula( ) = 0;virtual void Format( ) = 0; virtual void GetCell (string RC, cell*pCell) = 0; }

FIG. 4 is a block diagram illustrating a sample data structure of aspreadsheet object. The spreadsheet object comprises object datastructure 401, IBasic interface data structure 403, IDatabase interfacedata structure 404, the virtual function tables 402, 405, 406 andmethods 407 through 421. The object data structure 401 contains apointer to the virtual function table 402 and pointers to the IBasic andIDatabase interface. Each entry in the virtual function table 402contains a pointer to a method of the IUnknown interface. The IBasicinterface data structure 403 contains a pointer to the virtual functiontable 405. Each entry in the virtual function table 405 contains apointer to a method of the IBasic interface. The IDatabase interfacedata structure 404 contains a pointer to the virtual function table 406.Each entry in the virtual function table 406 contains a pointer to amethod of the IDatabase interface. Since the IBasic and IDatabaseinterfaces inherit the IUnknown interface, each virtual function table405 and 406 contains a pointer to the methods QueryInterface, AddRef,and Release. In the following, an object data structure is representedby the shape 422 labeled with the interfaces through which the objectmay be accessed.

The following pseudocode illustrates how a word processing programdetermines whether a spreadsheet object supports the IDatabaseinterface. if (pIBasic− > QueryInterface(“IDatabase”, &pIDatabase) = =S_OK) \* IDatabase supported else \* IDatabase not supportedThe pointer pIBasic is a pointer to the IBasic interface of the object.If the object supports the IDatabase interface, the methodQueryInterface sets the pointer pIDatabase to point to the IDatabasedata structure and returns the value S_OK.

Normally, an object can be instantiated (an instance of the objectcreated in memory) by a variable declaration or by the “new” operator.However, both techniques of instantiation need the class definition atcompile time. A different technique is needed to allow a word processingprogram to instantiate a spreadsheet object at run time. One techniqueprovides a global function CreateInstanceXX, which is defined in thefollowing.

static void CreateInstanceXX (REFIID iid, void **ppv)=0;

The method CreateInstanceXX (known as a class factory) instantiates anobject of class XX and returns a pointer ppv to the interface of theobject designated by parameter iid.

SUMMARY OF THE INVENTION

It is an object of the present invention to provide a method and systemfor generating links to source data incorporated within a compounddocument.

It is another object of the present invention for binding links tosource data.

It is another object of the present invention for interfacing with theselinks in a manner that is independent of the underlying source data.

It is another object of the present invention for linking to data nestedto an arbitrary level within a compound document.

These and other object, which will become apparent as the invention ismore fully described below, are provided by a method and system fornaming and binding data objects. In a preferred embodiment, a link to anobject incorporated is stored as a moniker. A moniker is an identifierobject that encapsulates the information needed to access theincorporated data and provides methods which bind to the incorporateddata.

BRIEF DESCRIPTION OF THE DRAWINGS

FIG. 1 is a block diagram of an example of a compound document.

FIG. 2 is a block diagram illustrating scheduling data, budgeting data,and explanatory data.

FIG. 3 is a block diagram illustrating typical data structures used torepresent an object.

FIG. 4 is a block diagram illustrating a sample data structure of aspreadsheet object.

FIG. 5 is a block diagram showing a sample compound document.

FIGS. 6, 7, and 8 are block diagrams illustrating the use of a monikerby a word processing program.

FIG. 9 is a block diagram of a generic composite moniker.

FIGS. 10A, 10B, and 10C are block diagrams illustrating monikercomposition.

FIG. 11 is a flow diagram of the method BindToObject of the classCFileMoniker.

FIG. 12 is a flow diagram of the function FileBindToObject.

FIG. 13 is a flow diagram of the method BindToObject of the classCItemMoniker.

FIG. 14 is a flow diagram of the method BindToObject of the classCCompositeMoniker.

FIGS. 15A through 15G are block diagrams illustrating the binding to anobject identified by a generic composite moniker.

FIG. 16 is a flow diagram illustrating the overall behavior ofimplementations of the method ComposeWith.

FIG. 17 is a flow diagram of the method ComposeWith of the classCCompositeMoniker.

FIGS. 18, 19A, 19B, 19C, 20A, 20B, 20C, 21A, 21B, and 21C are blockdiagrams illustrating sample generic composite monikers.

FIG. 22 is a block diagram illustrating moniker reduction.

FIG. 23 is a flow diagram of the method Reduce of the classCCompositeMoniker.

FIG. 24 is a flow diagram of the method Reduce of the sample classCAliasMoniker.

FIG. 25 is a flow diagram of the method IsEqual of the classCFileMoniker.

FIG. 26 is a flow diagram of the method IsEqual of the classCCompositeMoniker.

FIG. 27 is a flow diagram of the method Hash of the classCCompositeMoniker.

FIGS. 28A, 28B, and 28C are block diagrams illustrating composition withinverse monikers.

FIG. 29 is a flow diagram of the method Inverse of the classCCompositeMoniker.

FIG. 30 is a flow diagram of the method Inverse of the classCItemMoniker.

FIG. 31 is a flow diagram of the method ComposeWith of the classCItemMoniker.

FIG. 32 is a flow diagram of the method AnnihilateOne of the classCAntiMoniker.

FIG. 33 is flow diagram of the method ComposeWith of the classCAntiMoniker.

FIG. 34 is a block diagram illustrating a common prefix of genericcomposite monikers.

FIG. 35 is a flow diagram of the method CommonPrefixWith of the classCCompositeMoniker.

FIG. 36 is a flow diagram of the method CommonPrefixWith of the classCFileMoniker.

FIG. 37 is a flow diagram of the method CommonPrefixWith of the classCItemMoniker.

FIG. 38 is a flow diagram of the method CommonPrefixWith of the classCAntiMoniker.

FIG. 39 is a flow diagram of the function MonikerCommonPrefixWith.

FIG. 40 is a block diagram illustrating a relative path to moniker.

FIGS. 41A and 41B are block diagrams illustrating a usage of the methodRelativePathTo.

FIGS. 42A, 42B, and 42C comprise a flow diagram of the methodRelativePathTo of the class CCompositeMoniker.

FIG. 43 is a flow diagram of the function MonikerRelativePathTo.

FIG. 44 is a flow diagram of the method Enum of the classCCompositeMoniker.

FIG. 45 is a flow diagram of the method GetNext of the classCCompositeMonikerEnum.

FIG. 46 is a flow diagram of the method Next of the classCCompositeMonikerEnum.

FIG. 47 is a flow diagram of the method Create of the classCPointerMoniker.

FIG. 48 is a flow diagram of the method BindToObject of the classCPointerMoniker.

FIG. 49 is a block diagram illustrating a pointer moniker.

DETAILED DESCRIPTION OF THE INVENTION

The present invention provides a computer implemented method and systemfor naming and binding to linked data. In a preferred embodiment, acompound document that incorporates linked data stores a persistent datahandle, called a “moniker,” which is a reference to the link source. Amoniker is an identifier object that contains information to identifythe linked data and provides methods through which a program can bind tothe linked data. A binding method returns an instance of an interfacethrough which the linked data can be accessed. A moniker may link todata that is itself embedded data within another compound document. Forexample, a moniker may link to a range of cells within a spreadsheettable that is contained in a word processing document. A moniker maylink to data at any level within a compound document. During executionof the binding method, several applications may be invoked to locate thelink data. For example, to bind to the range of cells within aspreadsheet table that is within a word processing document, the wordprocessing program may be invoked to locate the embedded spreadsheettable and the spreadsheet program may be invoked to bind to the range ofcells. The present invention defines an interface through which amoniker is accessed. A moniker can identify source data that is storedpersistently or non-persistently.

In a preferred embodiment, monikers can be composed to form a compositemoniker. A composite moniker is conceptually a path to a source objectthat is identified by the concatenation of the monikers. For example, ifa moniker specifying a certain path (e.g., “c:\reports”) is composedwith a moniker specifying a certain file name (e.g., “Q3.doc”) then theresult is the complete path name to the file (e.g.,“c:\reports\Q3.doc”). Each composite moniker comprises a plurality ofcomponent monikers. The present invention provides a method and systemfor decomposing a composite moniker. In a preferred embodiment, eachmoniker provides a method that is used to retrieve each componentmoniker.

In a preferred embodiment, a moniker provides a reducing method whichreturns another moniker that is a more efficient representation of amoniker to the same source object. The reducing method may interpret amacro script that identifies the source object. Alternatively, thereducing method may evaluate a query request that identifies the sourceobject.

In a preferred embodiment, a moniker provides an equality method and ahash method. The equality method determines whether two monikersidentify the same source object. The hash method provides a hash valuefor a moniker. The equality method and hash method are used to implementhash tables indexed by monikers.

In a preferred embodiment, a moniker provides an inverse method thatgenerates another moniker that is the inverse of the moniker. When amoniker is composed with its inverse, the result is NULL. The inversemoniker is said to annihilate the moniker. An inverse moniker may beused, for example, to remove portions of a path and is analogous to the“..” functionality of traditional file systems.

In a preferred embodiment, a moniker provides a common prefix withmethod and a relative path to method. The common prefix with methoddetermines the common prefix portion of two monikers. For example, ifone moniker identifies the object “c:\reports\Q3.doc” and anothermoniker identifies the object “c:\reports\data\Q3.xls” the common prefixis “c:\reports”. The relative path to method generates relative path tomoniker that when composed with one moniker results in specifiedmoniker. For example, the moniker specifying the path that is theinverse of a moniker identifying object “Q3.doc” composed with a monikerspecifying the path “data\Q3.xls” is a relative path to moniker from themoniker “c:\reports\Q3.doc” to the moniker “c:\reports\data\Q3.xls”.Relative path to monikers are preferably used when identifying objectsby relative paths from another object.

In a preferred embodiment, the present invention provides severalimplementation monikers including a file moniker, an item moniker, ageneric composite moniker, a pointer moniker, and an anti moniker. Eachimplementation is referred to as a moniker class and has a classidentifier. A file moniker provides a moniker that conceptually is apath name in a file system. An item moniker provides a moniker thatconceptually identifies a portion of an object. A generic compositemoniker provides a mechanism for composing monikers with arbitraryimplementations. For example, a file moniker can be composed with anitem moniker to specify a portion of a file. A generic composite monikeris preferably created by the composing method of the file moniker. Apointer moniker is a moniker that wraps an instantiated source object ina moniker. A pointer moniker contains a pointer to the instantiatedsource object and when a pointer moniker is bound, it returns thepointer. An anti moniker is a moniker that is the inverse of othermonikers. When a moniker is composed with an anti moniker, the result isNULL. If a generic composite moniker is composed with an anti moniker,the result is a moniker comprising all but the last component moniker.The anti moniker annihilates the last component moniker of a genericcomposite moniker.

In a preferred embodiment of the present invention, an applicationprogram that creates a compound document controls the manipulation oflinked or embedded data generated by another application. Inobject-oriented parlance, this data is referred to as an object. (Thereference Budd, T., “An Introduction to Object-Oriented Programming,”Addison-Wesley Publishing Co., Inc., 1991, provides an introduction toobject-oriented concepts and terminology.) An object that is eitherlinked or embedded into a compound document is “contained” within thedocument. Also, a compound document is referred to as a “container”object and the objects contained within a compound document are referredto as “containee” objects. Referring to FIGS. 1 and 2, the schedulingdata 102 and budgeting data 103 are containee objects and the compounddocument 101 is a container object. The user can indicate to the wordprocessor that the user wants to edit a containee object, such as thebudgeting data 103. When the user indicates that the budgeting data 103is to be edited, the word processing program determines whichapplication should be used to edit the budgeting data (e.g., thespreadsheet program) and launches (starts up) that application. The usercan then manipulate the budgeting data using the launched application,and changes are reflected in the compound document. The same procedureis used whether the budgeting data is stored as an embedded or linkedobject.

FIG. 5 is a block diagram showing a sample compound document. The weeklyproject report 501 is the same compound document of FIG. 1. Theexecutive summary report 503, contains a budgeting chart 505 that islinked to the weekly project 501. The weekly project 501 contains anembedded spreadsheet 502. The embedded spreadsheet 502 was created bythe spreadsheet program 204 in FIG. 2. The data for this spreadsheet,the budget for the project, is stored within the storage the weeklyproject report 501 because it is an embedded object. The executivesummary document 503 is a compound document which contains native text504 and a contained object, the budget chart 505. The budget chart 505is linked to the data contained within in the spreadsheet 502 which isembedded in the compound document 501.

In a preferred embodiment, application programs (“applications”)cooperate using object linking and embedding facilities to create andmanipulate compound documents. An application that creates a compounddocument is referred to as a client application, and an application thatcreates and manipulates containee objects are referred to as serverapplications. An application can behave as both a client server.Referring to FIG. 2, the project management program 201 and thespreadsheet program 204 are server applications, and the word processingprogram 206 is a client application. A client application is responsiblefor selection of the various objects within the container object and forinvoking the proper server application to manipulate the selectedcontainee object. A server application is responsible for manipulatingthe contents of the containee objects.

In a preferred embodiment, applications are provided with animplementation-independent Application Programming Interface (API) thatprovides the object linking and embedding functionality. Appendix Acontains a detailed description of a preferred object linking andembedding system. The API is a set of functions that are invoked byclient and server applications. These functions manage, among otherthings, the setup and initialization necessary for client applicationsto send and receive messages and data to and from server applications.The API provides functions to invoke the correct server application toact upon a particular containee object and to manipulate containeeobjects.

In addition, the object linking and embedding API defines “interfaces”through which client applications can communicate with their containedobjects. An interface is a set of methods which abide by certain input,output, and behavior rules. If a contained object supports a particularinterface, the client application can invoke the methods of thatinterface to effect the defined behavior. In a preferred embodiment, theclient application is not allowed direct access to the object data; itmanipulates the object using the supported interfaces. A clientapplication is bound to a contained object through a pointer to aninterface. The client application accesses the object by invoking themethods of the interface. To access the object data, the methods maysend messages to the server application requesting the specified access.In a preferred embodiment, messages are sent between clients and serversusing interprocess communications mechanisms provided by the underlyingoperating system.

An example will help illustrate the relationship between a clientprocess and a server process. Referring again to FIG. 1, if a user wantsto edit the budgeting data 103 of the compound document 101, then thefollowing sequence of events occurs. First, the user starts up the wordprocessor program, which is dynamically linked to the object linking andembedding API. Second, the user opens the compound document for editing.Third, the user selects the budgeting data, which is a containee object,and indicates that the selected object is to be edited. Fourth, theclient application invokes a client API routine for performing an actionon an object passing the routine a handle (which uniquely identifies theselected object) to the object and an indicator that the action is edit.Fifth, the client API routine determines that the spreadsheet programprovides the actions for the budgeting data. Sixth, the client API codestarts up the spreadsheet program as a server process, if it is notalready started. Seventh, the word processor application sends a messageto the spreadsheet program that it should edit the budgeting data.Eighth, the server API code receives the request to edit and invokes aroutine in the spreadsheet program for editing the data. When editing iscomplete, the spreadsheet routine returns to the server API code. Theserver API code sends a message to the word processor application toindicate that editing is complete. The client API code receives themessage and returns from its invocation. Upon return from theinvocation, the word processor application knows that the editing iscomplete.

In addition to the client and server API, the object linking andembedding facilities of the present invention provide information toclient and server applications through a persistent global “registry.”This registry is a database of information such as (1) for each type ofobject, the server application that implements the object type, (2) theactions that the each server application provides to clientapplications, (3) where the executable files for each server applicationare located, and (4) whether each server application has an associatedobject handler. An object handler is a collection of functions in adynamic link library. An object handler can be used to provide certainfunctions without launching the server.

FIGS. 6, 7, and 8 are block diagrams illustrating the use of a monikerby a word processing program. In FIG. 6, the document “RPT.DOC” 601contains a link 602 to the chart file 603. The link 602 is a monikerthat is persistently stored in the document 601. The persistent storageof the moniker includes the class identifier “CLSID_FileMoniker” and thename of the chart file 603 (“Q3.CHT”). When the word processing programdisplays the chart of chart file 603, it first instantiates a monikerobject of type CLSID_FileMoniker, requests the moniker to load itspersistent data (e.g., “Q3.CHT”), and then requests the moniker to bindto the file indicated by the loaded data. FIG. 7 is a block diagramillustrating the instantiation of a moniker object. The word processingprogram first reads in the class identifier of link 602. To determinehow to instantiate an object of that class, the program accesses theglobal registry 704. The global registry includes a mapping from classidentifiers to the location of a class factory to create an instance ofthat class. For example, table 704B indicates that the class factory forthe moniker class identified by CLSID_FileMoniker is contained in thedynamic link library named “FileMkr.DLL.” The program links to the classfactory code within the dynamic link library 706. The program invokesthe function CreateInstance to create an instance of an object of classCFileMoniker 702 (a file moniker). The program then requests theIPersistStream interface of the file moniker. The IPersistStreaminterface (described in detail in Appendix A) provides methods throughwhich the internal state (e.g., “Q3.CHT”) of a moniker can be saved topersistent storage and then loaded into memory from the persistentstorage. Using the methods of the IPersistStream interface, the programloads the moniker internal state persistently stored in link 602 intothe file moniker 702. The program then requests the IMoniker interfaceto the file moniker 702. The pointer to the IMoniker interface is storedin pointer 701. FIG. 8 is a block diagram illustrating the binding ofthe file moniker 702 to the chart file 603. When a binding method of thefile moniker 702 is invoked, the method determines the class identifierfor the file identified by the file moniker by accessing the globalregistry table 704A. The class identifier for files with suffix “CHT” isCLSID_Chart. The program then retrieves the class factory for the classCLSID_Chart from the registry table 704B. The program links to thedynamic link library “CHART.DLL” 806. The program then invokes theCreateInstance method within the dynamic link library 806, which createsan instance of a chart object 807 and returns a pointer to theIDataObject interface. The IDataObject interface (described in detail inAppendix A) provides methods to pass data to and from an object (e.g.,methods GetData and SetData). Through the chart object 807, the programcan access the chart file 603 through the chart server 808.

In a preferred embodiment, a moniker is an object that supports theIMoniker interface of Code Table 3. The IMoniker interface inherits theIPersistStream interface; thus, monikers can be saved to and loaded fromstreams. The persistent form of a moniker contains the class identifier(CLSID) of its implementation which is used during the loading process,and new classes of monikers can be created transparently to clients.

The IMoniker interface provides for binding to the object to which itpoints, which is supported by the method BindToObject. This method takesas a parameter the interface identifier by which the caller wishes totalk to the object, runs whatever algorithm is necessary in order tolocate the object, then returns a pointer of that interface type to thecaller. Each moniker class can store arbitrary data its persistentrepresentation, and can run arbitrary code at binding time.

If there is an identifiable piece of persistent storage in which theobject referenced by the moniker is stored, then the methodBindToStorage can be used to access it. Many objects have suchidentifiable storage (e.g., a file), but some, such as the objects whichare the ranges in a spreadsheet do not.

In a preferred embodiment, a particular moniker class is designed to beone step along the path (a component) to a data source. These componentscan be composed together to form a moniker which represents the completepath to the data source. For example, the moniker stored inside thechart of FIG. 5 might be a generic composite moniker formed from threecomponent as illustrated in FIG. 9. This composite is itself a moniker;it is a moniker which is a sequenced collection of other compositemonikers. The composition is generic in that it has no knowledge of thecomponent monikers involved other than that they are monikers. CODETABLE 3 class IMoniker : IPersistStream { virtual HRESULTBindToObject(pbc, pmkToLeft, iidResult, ppvResult) = 0; virtual HRESULTBindToStorage(pbc, pmkToLeft, iid, ppvObj) = 0; virtual HRESULTReduce(pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced) = 0; virtualHRESULT ComposeWith(pmkRight, fOnlyIfNotGeneric, ppmkComposite) virtualHRESULT Enum(fForward, ppenmMoniker) = 0; virtual HRESULTIsEqual(pmkOtherMoniker) = 0; virtual HRESULT Hash(pdwHash) = 0; virtualHRESULT IsRunning(pbc, pmkToLeft, pmkNewlyRunning) = 0; virtual HRESULTGetTimeOfLastChange(pbc, pmkToLeft, pfiletime) = 0; virtual HRESULTInverse(ppmk) = 0; virtual HRESULT CommonPrefixWith(pmkOther,ppmkPrefix) = 0; virtual HRESULT RelativePathTo(pmkOther, ppmkRelPath);virtual HRESULT GetDisplayName(pbc, pmkToLeft, lplpszDisplayName) = 0;virtual HRESULT ParseDisplayName(pbc, pmkToLeft, lpszDisplayName,pcchEaten, ppmkOut) = 0; virtual HRESULT IsSystemMoniker(pdwMksys); };

The example of FIGS. 6, 7, and 8 illustrate the use of a moniker thatidentifies a file. The present invention allows moniker to be combined(composed) to an arbitrary level. FIGS. 10A, 10B, and 10C illustratemoniker composition. For example, if the chart file 603 containedmultiple charts, it would be useful to designate a specific chart to bethe source of a link. In one embodiment of the present invention, amoniker class named “CChartMoniker” could be implemented by thedeveloper of the chart program. A chart moniker 1001 would contain aname of a chart file (“Q3.CHT”) and an indication of a chart within thefile (“CHART2”). The methods of the class CChartMoniker would have abehavior similar to that provided by the class CFileMoniker plusbehavior needed to bind to the identified chart. As described above, thepresent invention allows two monikers to be composed to form a thirdmoniker. By composing monikers, a developer can use an implementationdeveloped by someone else. For example, the developer of the chartprogram could define and implement the class CChartMoniker to containonly an indication of a chart within a file. The class CChartMoniker canbe developed assuming that an instance of chart moniker 1003 will becomposed with a file moniker (e.g., file moniker 1002). In a preferredembodiment, to facilitate the composing of monikers, a moniker of classCCompositeMoniker is defined and implemented. The classCCompositeMoniker encapsulates any two monikers into single genericcomposite moniker. The generic composite moniker 1004 encapsulates thefile moniker 1002 and the chart moniker 1003. A link to a chart isstored as a generic composite moniker which encapsulates a file monikerand a chart moniker. The client of the link need only know that themoniker supports the IMoniker interface.

In the following, each method of the IMoniker interface is defined. Inaddition, several implementations of various methods are described. Inparticular, implementations of methods of the classes CFileMoniker,CCompositeMoniker, and CItemMoniker are described. The classCFileMoniker (a file moniker) is a moniker class that identifies a pathname in a file system. When a file moniker is bound to, it determinesthe class of the file by using the persistent global registry, ensuresthat the appropriate class server is running, and then requests theserver to open the file. The class CCompositeMoniker (a genericcomposite moniker) is a moniker class that identifies a composition oftwo monikers (a left and a right moniker). When a generic compositemoniker is bound to, it invokes the binding method of the right monikerindicating that the left moniker is composed with the right moniker. Theright moniker performs its binding behavior, which may include invokingthe binding method of the left moniker. The class CItemMoniker (an itemmoniker) is a moniker class that implements behavior common to theidentification of containee objects. An item moniker can be used toidentify, for example, a chart contained within a chart file or a rangewithin a spreadsheet. An item moniker uses the IOleItemContainerinterface (described in detail in Appendix A) to interact with thecontainer. Code Table 4 contains the class definitions for a filemoniker, a generic composite moniker, an item moniker, an anti moniker,and a pointer moniker. An anti moniker and a pointer moniker aredescribed below in detail. A file moniker contains a string (m_szPath)indicating a path name and a count of anti monikers (m_cAnti). A genericcomposite moniker contains a pointer to the left moniker (m_pmkLeft) anda pointer to the right moniker (m_pmkRight) of the generic composite anda flag (m_fReduced) indicating whether the composite is reduced. An itemmoniker contains a pointer to a string (m_lpszItem) that defines theitem. CODE TABLE 4 class CFileMoniker: IMoniker { char FAR * m_szPath;UINT m_cAnti; } class CCompositeMoniker: IMoniker { LPMONIKER m_pmkLeft;LPMONIKER m_pmkRight; BOOL m_fReduced; } class CItemMoniker: IMoniker {char FAR * m_lpszItem; } class CAntiMoniker: IMoniker { ULONG m_count; }class CPointerMoniker: IMoniker { LPUNKNOWN m_punk; }IMoniker::BindToObject HRESULT IMoniker::BindToObject(pbc, pmkToLeft,iidResult, ppvResult)

The method BindToObject locates and loads the object semanticallyreferred to by this moniker according to the interface specified byiidResult and returns a pointer to the object through ppvResult. In thefollowing, the term “this moniker” refers to the moniker for which amethod is invoked. In general, each class of moniker is designed to beused as one component in a generic composite moniker which gives thecomplete path to the referenced object. In a generic composite, anycomponent moniker has a certain prefix of the generic composite to itsleft, and a certain suffix to its right. If the method BindToObject isinvoked on a component moniker, then the implementation of BindToObjecttypically requires certain services of the object indicated by theprefix to its left. Item monikers, for example, require theIOleItemContainer interface of the object to their left. The ItemMoniker implementation of the method BindToObject (as described below)recursively calls pmkToLeft->BindToObject in order to obtain thisinterface. If the moniker does not need services of the object to itsleft, yet one is provided by the caller nevertheless, no error occurs.Rather, the moniker ignores the object to its left. If the objectindicated by the moniker does not exist, then the error MK_E_NOOBJECT isreturned.

In general, binding a moniker can be a complicated process, since it mayneed to launch servers, open files, etc. This may involve binding toother objects, and the binding components of a generic composite to theright of certain components will require the same other objects. Inorder to avoid loading the object, releasing it, then having it loadedagain later, the method BindToObject can use the bind context passedthrough the pbc parameter to defer releasing objects until the bindingprocess overall is complete. The bind context is described in detail inAppendix A.

Binding to a moniker a second time typically returns the same runningobject as binding the first time, rather than reloading it again fromstorage. This functionality is supported with a running object table.The running object table is a lookup table keyed by a moniker whosevalues are pointers to the corresponding now-running object. As objectsbecome running, they register themselves in this table. Implementationsof the method BindToObject uses this table to determine if the object towhich they point is already running. More precisely, if the passedpmkToLeft parameter is NULL (and this is not an error; that is, themoniker does not require something to its left), then the moniker fullyreduces itself, then looks itself up in the running object table, andreturns the pointer to the object found there. The running object tableis described in detail in Appendix A.

The following table describes the parameters of the method BindToObject:Argument Type Description pbc IBindCtx* the bind context to be used forthis binding operation. pmkToLeft IMoniker* the moniker of the object tothe left of this moniker. iidResult IID the requested interface by whichthe caller wishes to connect to the object. ppvResult void** onsuccessful return, a pointer to the instantiated object is placed here,unless BINDFLAGS_JUSTTESTEXISTENCE was specified in the binding options,in which case NULL may be returned instead. return value HRESULT S_OK,MK_E_NOOBJECT, STG_E_ACCESSDENIED, MK_E_EXCEEDEDDEADLINE,MK_E_CONNECTMANUALLY, MK_E_INTERMEDIATEINTERFACENOTSUPPORTED.E_OUTOFMEMORY, E_NOINTERFACE

FIG. 11 is a flow diagram of the method BindToObject of the classCFileMoniker. This method determines the class identifier of the file,determines the server for that file, launches the server (if necessary),and requests the server to open and bind to the file. In step 1101, if amoniker to the left of this moniker is specified, then the methodcontinues at step 1105, else the method continues at step 1102. In steps1102 through 1104, the method determines whether the object identifiedby the moniker to the left is in the running object table. If the objectto the left is in the running object table, then the requested interface(iidResult) is retrieved from that object and returned. In step 1102, ifthe object to the left is in the running object table, then the methodcontinues at step 1103, else the method continues at step 1105. In step1103, the method retrieves a pointer to the object to the left from therunning object table. In step 1104, the method retrieves the requestedinterface from the object to the left by invoking the methodQueryInterface of the object to the left and then returns. In step 1105,the method retrieves the class identifier corresponding to the path(m_szPath) of this moniker. The class identifier is preferably retrievedfrom a persistent global registry that maps file name suffixes to classidentifiers. In step 1106, the method invokes the functionFileBindToObject to bind to the file and returns the requestedinterface. The method then returns.

FIG. 12 is a flow diagram of the function FileBindToObject. Thisfunction is passed a class identifier and a requested interface. Thisfunction instantiates an object of the passed class identifier andreturns a pointer to the requested interface. In step 1201, the functioncreates an instance of an object of the passed class identifier andretrieves the IUnknown interface. In step 1202, the function retrievesthe IPersistFile interface from the instantiated object. TheIPersistFile interface provides methods to load and save files and isdescribed in detail in Appendix A. In step 1203, the functioninitializes binding options, which are described in detail in AppendixA. In step 1204, the function invokes the method Load of theIPersistFile interface to load the data for the created object. In step1205, the function retrieves the requested interface from the createdobject and returns.

FIG. 13 is a flow diagram of the method BindToObject of the classCItemMoniker. In step 1301, if no moniker to the left of this moniker isspecified, then the method returns an error, else the method continuesat 1302. An item moniker identifies a containee object and requires amoniker to a container object to its left. In step 1302, the methodinvokes the method BindToObject of the moniker of the object to theleft. The method requests the IOleItemContainer interface from theobject to the left. In step 1303, the method invokes the methodGetObject of the IOleItemContainer interface and passes the item name(m_lpszItem) and the requested interface. The method then returns withthe interface retrieved by the method GetObject.

FIG. 14 is a flow diagram of the method BindToObject of the classCCompositeMoniker. The method binds to a generic composite moniker in aright-to-left manner. Conceptually; a generic composite moniker forwardsthe bind request to its last component moniker informing the lastcomponent moniker of the moniker to its left in the composite. The lastcomponent moniker, if it needs to, recursively binds to the object toits left. In step 1401, if no moniker to the left of this moniker isspecified, the method continues at step 1402, else the method continuesat step 1405. In step 1402, if this moniker is in the running objecttable, then the method continues at step 1403, else the method continuesat step 1405. In step 1403, the method retrieves a pointer to the objectfrom the running object table. In step 1404, the method retrieves therequested interface of the object by invoking the method QueryInterfaceof the object and returns. In steps 1405 through 1408, the methodinvokes the method BindToObject of the last component moniker of thismoniker passing a moniker comprising the prefix component monikers asthe moniker to the left. In step 1405, if no monikers to the left ofthis moniker is specified, then the method continues at step 1406, elsethe method continues at step 1407. In step 1406, the method creates anew left moniker that contains all but the last component moniker ofthis moniker. The method then invokes the method BindToObject of thelast component moniker of this moniker passing it the newly-created leftmoniker and the requested interface in step 1408 and returns. In step1407, the method composes the moniker to the left with all but the lastcomponent moniker of this moniker by invoking the method ComposeWith ofthe moniker to the left. The method then invokes the method BindToObjectof the last component moniker of this moniker passing it thenewly-created composed moniker and the identifier of the requestedinterface in step 1408 and returns.

FIGS. 15A through 15G are block diagrams illustrating the binding to anobject identified by a generic composite moniker. FIG. 15A illustratesthe generic composite moniker that is to be bound. The generic compositemoniker comprises components 1501, 1502, and 1503. The componentmonikers 1501, 1502, and 1503 represent a reference to an objectidentified by “C:\Q3RPT.DOC\SALESTBL\R2C2:R7C4”. The component moniker1501 is the first component moniker of the generic composite moniker,and the component moniker 1503 is the last component moniker of thegeneric composite moniker. The component monikers 1502 and 1503 are allbut the first component monikers of the generic composite moniker, andthe component monikers 1501 and 1502 are all but the last componentmonikers of the generic composite moniker. These component monikers arecomposed using generic composite monikers 1504 and 1505. To bind to theobject identified by the generic composite moniker 1504, the methodBindToObject is invoked indicating that there is no moniker to the leftand indicating the identifier of a requested interface. Since moniker1504 is a generic composite moniker, the method represented by the flowdiagram of FIG. 14 is executed. Since there is no moniker to the leftand since for this example the generic composite moniker 1504 is not inthe running object table, the method continues at step 1406. In step1406, the method creates the generic composite moniker 1506 thatcontains all but the last component moniker of the generic compositemoniker 1504. In step 1408, the method invokes the method BindToObjectof the last component moniker 1503 passing the generic composite moniker1506 as the moniker to the left and the identifier of the requestedinterface. Since the component moniker 1503 is an item moniker, themethod represented by the flow diagram of FIG. 13 is executed. Since amoniker to the left is specified, step 1302 is executed. In step 1302,the method invokes the method BindToObject of the moniker to the left(generic composite moniker 1506) passing no moniker to the left andrequesting the IOleItemContainer interface. Since the generic compositemoniker 1506 is a generic composite moniker, the method represented bythe flow diagram of FIG. 14 is executed. Since no moniker to the left isspecified, the method continues at step 1406. In step 1406, the methodsets the new left moniker to the moniker 1501. In step 1408, the methodinvokes the method BindToObject of the item moniker 1502 passing the newleft moniker 1501 and requesting the passed interface, which is theinterface to the IOleItemContainer. Since the item moniker 1502 is anitem moniker, the method represented by the flow diagram of FIG. 13 isexecuted. Since there is a moniker to the left is specified, step 1302is executed. In step 1302, the method invokes the method BindToObject ofthe moniker to the left (file moniker 1501). Since the file moniker 1501is a file moniker, the method represented by the flow diagram of FIG. 11is executed. Since no moniker to the left is specified, the methodcontinues at step 1105. In steps 1105 and 1106, the method binds to thefile object and returns the requested interface as shown in FIG. 15G.The invocation of the method BindToObject of the item moniker 1503eventually in step 1303 invokes the method GetObject of theIOleItemContainer interface returned in step 1302 to retrieve therequested interface.

IMoniker::ComposeWith

RESULT IMoniker::ComposeWith(pmkRight, fOnlyIfNotGeneric, ppmkComposite)

This method ComposeWith returns a new moniker which is a compositeformed with this moniker on the left and the passed moniker (pmkRight)on the right. There are two kinds of composite monikers: those compositemonikers that know nothing about their component monikers other thanthat they are monikers (a generic composite moniker), and thosecomposite monikers that know more (a special composite moniker). Forexample, a file moniker containing a relative path may be composed on tothe end of another file moniker. The resulting composite moniker couldbe a new file moniker containing the complete path. The new file monikeris a special composition. A special composition is useful for monikersthat are capable of collapsing a path within a storage domain to a moreefficient representation in a subsequent reduction.

Each moniker class may have a set of other kinds of special monikersthat can be composed onto the end of it in a non-generic way. Eachimplementation of the method ComposeWith examines the passed moniker onthe right (pmkRight) to see if it is such a special moniker for theimplementation. If the specified moniker on the right is special, thenthe implementation does whatever is appropriate for that special case.If it is not, then the passed flag fOnlyIfNotGeneric controls whatoccurs. If flag fOnlyIfNotGeneric is true, then NULL is passed backthrough parameter ppmkComposite and the status MK_E_NEEDGENERICreturned; if fOnlyIfNotGeneric is false, then a generic compositemoniker is created using the function CreateGenericComposite andreturned.

If the specified moniker on the right (pmkright) completely annihilatesthis moniker, the resulting composite is empty and the parameterppmkComposite is set to NULL and the status S_OK returned.

Composition of monikers is an associative operation. That is, if A, B,and C are monikers, then(A∘B)∘Cis always equal toA∘(B∘C)where ∘ represents the composition operation.

The following table describes the parameters of the method ComposeWith:Argument Type Description pmkRight IMoniker* the moniker to compose ontothe end of the receiver. fOnlyIfNotGeneric BOOL controls whether acomposite moniker should be returned when the right moniker is not aspecial moniker for this moniker. ppmkComposite IMoniker* on exit, theresulting composite moniker. Possibly NULL. return value HRESULT S_OK,MK_E_NEEDGENERIC

FIG. 16 is a flow diagram illustrating the overall behavior ofimplementations of the method ComposeWith. In step 1601, if the monikerto the right (pmkRight) is special, then the method continues at step1602, else the method continues at step 1603. In step 1602, the methodperforms a composition associated with the special moniker and returns.In step 1603, if the caller wants a generic composition when no specialcomposition occurs (fOnlyIfNotGeneric==FALSE), then the method continuesat step 1604, else the method continues at step 1605. In step 1604, themethod creates a generic composite moniker by invoking the functionCreateGenericMoniker and returns. In step 1605, the method returns anindication that composite moniker is NULL and sets the return flag toindicate that no special or generic composition occurred.

FIG. 17 is a flow diagram of the method ComposeWith of the classCCompositeMoniker. The method invokes the functionCreateGenericComposite (described below) and returns. CODE TABLE 4CreateGenericComposite (pmkFirst, pmkRest, ppmkComposite) { Case1:pmkFirst− > ComposeWith (pmkRest, TRUE, ppmkComposite) if (nocomposition occurred) CCompositeMoniker::Create (pmkFirst, pmkRest,ppmkComposite) Case2: pmkFirst− > ComposeWith (pmkFirstOfRest, TRUE,&pmk) if (no composition occurred) CCompositeMoniker::Create(pmkFirst,pmkRest, ppmkComposite) else if (pmk! = NULL) CreateGenericComposte(pmk, pmkAllButFirstOfRest, ppmkComposite) else *ppmkComposite =pmkAllButFirstOfRest Case3: pmkLastOfFirst− > ComposeWith(pmkRest, TRUE,&pmk); if (no composition occurred) CCompositeMoniker::Create(pmkFirst,pmkRest, ppmkComposite) else if (pmk! = NULL) CreateGenericComposite(pmkAllButLastOfFirst, pmk, ppmkComposite) else *ppmkComposite =pmkAllButLastOfFirst Case4: pmkLastOfFirst− > ComposeWith(pmkFirstOfRest, TRUE, &pmk) if (no composition occurred)CCompositeMoniker::Create(pmkFirst, pmkRest, ppmkComposite) else if(pmk! = NULL) CreateGenericComposite (pmkAllButLastOfFirst, pmk, &pmk2)CreateGenericComposite (pmk2, pmkAllButFirstOfRest, ppmkComposite) elseCreateGenericComposite (pmkAllButLastOfFirst, pmkAllButFirstOfRest,ppmkComposite) }CreateGenericCompositeHRESULT CreateGenericComposite(pmkFirst, pmkRest, ppmkComposite)

The function CreateGenericComposite allocates and returns a new genericcomposite moniker. The parameters pmkFirst and pmkRest point to thefirst and trailing monikers that are to comprise the generic compositemonikers, respectively. Either pmkFirst or pmkRest may be a genericcomposite moniker, or another kind of moniker. The following tabledescribes the parameters of the function CreateGenericComposite:Argument Type Description pmkFirst IMoniker* the first moniker in thenew composite. pmkRest IMoniker* the trailing (rest) moniker in the newcomposite. ppmkComposite IMoniker* a pointer to the new composite.return value HRESULT S_OK, E_OUTOFMEMORY

Code Table 4 contains C++ pseudocode for the functionCreateGenericComposite. The function handles four specific cases. Thefirst case occurs when neither the first moniker (pmkFirst) nor the restmoniker (pmkRest) are generic composite monikers. The second case occurswhen the first moniker is not a generic composite moniker, but the restmoniker is a generic composite moniker. The third case occurs when thefirst moniker is a generic composite moniker, but the rest moniker isnot a generic composite moniker. The fourth case occurs when both thefirst moniker and the rest moniker are generic composite monikers.

In the first case, the function CreateGenericComposite invokes themethod ComposeWith of the first moniker passing the rest moniker andspecifying that a composition should occur only if not generic. If therest moniker is not a special moniker for the first moniker, then nocomposition occurs and the function creates a composite moniker byinvoking the method Create of the class CCompositeMoniker passing thefirst moniker and the rest moniker. The method Create of the classCCompositeMoniker creates a generic composite moniker that points to thespecified monikers and returns a pointer to the created moniker. FIG. 18illustrates the resulting generic composite moniker 1803 of the firstcase when the rest moniker 1802 is not a special moniker of the firstmoniker 1801. In the second case, the function CreateGenericCompositeinvokes the method ComposeWith of the first moniker passing the firstcomponent moniker of the rest moniker. If the first component moniker ofthe rest moniker is not a special moniker for the first moniker, then nocomposition occurs and the method creates a composite moniker byinvoking the method Create of the class CCompositeMoniker passing thefirst moniker and the rest moniker. FIG. 19A illustrates arepresentative resulting generic composite moniker 1905 when the firstcomponent moniker 1903 of the rest moniker 1902 is not a special monikerof the first moniker 1901. If, however, a composition of the firstmoniker and the first component of the rest moniker occurs and a monikeris returned, then the function recursively calls the functionCreateGenericComposite to compose the moniker returned with all but thefirst component moniker of the rest moniker. FIG. 19B illustrates theresulting generic composite moniker 1907 that contains the compositemoniker 1906, which is the composition of the first moniker and thefirst component moniker of the rest moniker, and contains the moniker1904, which includes all but the first component moniker of the restmoniker. If the composition of the first moniker and the first componentmoniker of the rest moniker resulted in an annihilation of the monikers(pmk==NULL), then the function returns a pointer to a moniker formed byall but the first component moniker of the rest moniker as illustratedin FIG. 19C. In the third case, the function CreateGenericCompositeinvokes the method ComposeWith of the last component moniker of thefirst moniker passing the rest moniker. If the rest moniker is not aspecial moniker for the last component moniker of the first moniker,then no composition occurs and the function creates a composite monikerby invoking the method Create of the class CCompositeMoniker passing thefirst moniker and the rest moniker as illustrated by the representativegeneric composite moniker in FIG. 20A. If, however, a compositionoccurs, and a moniker is returned, then the method recursively invokesthe function CreateGenericComposite passing all but the last componentmoniker of the first component moniker and the returned moniker asindicated in FIG. 20B. If, however, the composition of the first monikerwith the first component moniker of the rest moniker resulted in anannihilation of the monikers, then the function returns a monikercomprising all but the last component moniker of the first moniker asthe composite moniker as illustrated by FIG. 20C. In the fourth case,the function CreateGenericComposite invokes the method ComposeWith ofthe last component moniker of the first moniker passing the firstcomponent moniker of the rest moniker. If the first component moniker ofthe rest moniker is not a special moniker for the last component monikerof the first moniker, then no composition occurs and the functioninvokes the method Create of the class CCompositeMoniker passing thefirst moniker and the rest moniker resulting in the sample genericcomposite moniker of FIG. 21A. If, however, a composition does occurwithout annihilation, then the function recursively invokes the functionCreateGenericComposite passing the composed moniker and all but the lastcomponent moniker of the first moniker. The function then recursivelyinvokes the function CreateGenericComposite passing the resultingcomposite moniker and all but the first component moniker of the restmoniker resulting in the representative composite moniker of FIG. 21B.If the composition results in annihilation of the last component monikerof the first moniker and the first component moniker of the restmoniker, then the function recursively invokes the functionCreateGenericComposite passing all but the last component moniker of thefirst moniker and all but the first component moniker of the restmoniker resulting in the representative generic composite moniker ofFIG. 21C.

IMoniker::Reduce

HRESULT IMoniker::Reduce(pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced)

The method Reduce requests a moniker to re-write itself into anotherequivalent moniker. This method returns a new moniker that will bind tothe same object, but does so in a more efficient way. This capabilityhas several uses:

-   -   It enables the construction of user-defined macros or aliases as        new kinds of moniker classes. When reduced, the moniker to which        the macro evaluates is returned.    -   It enables the construction of a kind of moniker which tracks        data as it moves about. When reduced, the moniker of the data in        its current location is returned.    -   On certain file systems which support an ID-based method of        accessing files that is independent of file names, a file        moniker could be reduced to a moniker which contains one of        these IDs.

FIG. 22 shows an example of moniker reduction. This example illustratesthe reduction of a moniker which names the net income entry for thisyear's report in the “Projects” directory of the current user's homedirectory. (Note that the particular classes of monikers used here arefor illustrative purposes only.) Several monikers in this example arereduced to something completely different, and some bind to somethingduring their reduction, but some do not. For example, to reduce thealias “Home”, the reduction must access the information that “Home” wasan alias for “\\server\share\fred”. Monikers may reduce to themselves,when they cannot be rewritten any further. A moniker which reduces toitself indicates this by returning itself through parameter ppmkReducedand the returning status code MK_S_REDUCED_TO_SELF. A moniker whichreduces to nothing returns NULL in parameter ppmkReduced and the statuscode S_OK. If a moniker does not reduce to itself, then this method doesnot reduce this moniker in-place; instead, it returns a new moniker.

The reduction of a moniker which is a composite of other monikersrepeatedly reduces the component monikers of which it is composed untilthey all reduce to themselves, and then returns the composite of thereduced components. The parameter dwReduceHowFar controls the stoppingpoint of the reduction process. It controls to what extent the reductionshould be carried out. It has the following values.

typedef enum tagMKRREDUCE {

-   -   MKRREDUCE_ONE=3<<16,    -   MKRREDUCE_TOUSER=2<<16,    -   MKRREDUCE_THROUGUSER=1<<16,    -   MKRREDUCE_ALL=0    -   } MKRREDUCE;

These values have the following semantics. Value DescriptionMKRREDUCE_ONE Perform only one step of reduction on this moniker. Ingeneral, the caller will have to have specific knowledge as to theparticular kind of moniker in question in order to be able to usefullytake advantage of this option. MKRREDUCE_TOUSER Reduce this moniker tothe first point where it first is of the form where it representssomething that the user conceptualizes as being the identity of apersistent object. For example, a file name would qualify, but a macroor an alias would not. If no such point exists, then this option shouldbe treated as MKRREDUCE_ALL. MKRREDUCE_THROUGUSER Reduce this moniker tothe point where any further reduction would reduce it to a form whichthe user does not conceptualize as being the identity of a persistentobject. Often, this is the same stage as MKRREDUCE_TOUSER. MKRREDUCE_ALLReduce the entire moniker, then, if needed reduce it again and again tothe point where it reduces to simply itself.

The following table describes the parameters of the method Reduce:Argument Type Description pbc IBindCtx* The bind context to use in thisoperation. dwReduceHowFar DWORD Indicates to what degree this monikershould be reduced. ppmkToLeft IMoniker** On entry, the moniker which isthe prefix of this one in the composite in which it is found. On exit,the pointer is either NULL or non-NULL. Non-NULL indicates that what waspreviously thought of as the prefix should be disregarded and themoniker returned through ppmkToLeft considered the prefix in its place.NULL indicates that the prefix should not be so replaced. Thus, mostmonikers will NULL out this parameter before returning. ppmkReducedIMoniker** On exit, the reduced form of this moniker. Possibly NULL.return value HRESULT S_OK, MK_S_REDUCED_TO_SELF, MK_E_EXCEEDEDDEADLINE.

FIG. 23 is a flow diagram of the method Reduce of the classCCompositeMoniker. The method reduces each of the component monikers ina left-to-right manner and creates a composite of the result. If any ofthe component monikers do not reduce to themselves (and thus, thegeneric composite moniker overall does not reduce to itself), then theprocess of reduction is repeated. In an alternate embodiment, the methodtracks component monikers that reduce to themselves and suppresses theirre-reduction. In step 2301, if this moniker is already reduced asindicated by the data member m_fReduced, then the method continues atstep 2302, else the method continues at step 2303. In step 2302, themethod sets the pointer to the reduced moniker to point to this monikerand returns indicating that the moniker reduced to itself. In step 2303,if the left moniker is NULL, then the method continues at step 2306,else the method continues at step 2304. In step 2304, the method invokesthe method Reduce of the left moniker passing the moniker to the left ofthis moniker and returning a left reduced moniker (pmkLeftReduced). Instep 2305, if no error occurred or the left moniker reduced to itself,then the method continues at step 2306, else the method returns anerror. If this moniker has no right moniker (m_pmkRight), then themethod continues at step 2309, else the method continues at step 2307.In step 2307, the method invokes the method Reduce of the right monikerpassing an indicator of a NULL moniker to the left and returning a rightreduced moniker (pmkRightReduced). In step 2308, if no error occurred orthe right moniker reduced to itself, then the method continues at step2309, else the method returns an error. In step 2309, if both the leftand right monikers reduced to themselves, then the method continues atstep 2310, else the method continues at step 2312. In step 2310, themethod sets the state of this moniker to reduced (m_fReduced). In step2311, the method sets the pointer to the reduced moniker to point tothis moniker and the method returns with an indication that this monikerreduced to itself. In step 2312, the method invokes the method Create ofthe class CCompositeMoniker passing the left reduced moniker and theright reduced moniker and returning the result as a composite reducedmoniker (pmkCompositeReduced). In step 2313, the method sets the stateof the composite reduced moniker to reduced (m_fReduced). In step 2314,the method sets the pointer to the reduced moniker to point to thecomposite reduced moniker and returns.

FIG. 24 is a flow diagram of the method Reduce of the sample classCAliasMoniker. The reduction of an alias moniker is illustrated in FIG.22. In step 2401, if the alias moniker indicates the home directory,then the method continues at step 2402, else the method tests for othertypes of alias indicated by the ellipsis. In step 2402, the methodretrieves the network volume associated with the user. In step 2403, themethod retrieves the home directory for the user. In step 2404, themethod creates a net volume moniker passing it the name of the networkvolume. In step 2405, the method creates a file moniker passing it thename of the user's home directory. In step 2406, the method creates ageneric composite moniker passing it the net volume moniker and the filemoniker. In step 2407, the method sets the generic composite moniker toindicate that it is reduced. In step 2408, the method sets the pointerto the reduced moniker to the composite moniker (pmkCompositeReduced)and returns. CODE TABLE 5 { A = CreateMoniker (cFileMoniker,“c:\reports\expenses\weekly”) B = CreateMoniker (cFileMoniker,getcurrentusername) C = CreateMoniker (cFileMoniker, dayofweek(getcurrentdate-oneday)) Result = A∘B∘C }

CODE TABLE 6 { A = CreateMoniker (cFileMoniker, “c:\taxes”) Prompt“Enter year:”, year B = CreateMoniker (cFileMoniker, year) C =CreateMoniker (cFileMoniker, “\1040.XLS”) D = CreateMoniker(cItemMoniker, “R1C1:R10C10”) Result A∘B∘C∘D }

In a preferred embodiment, a macro moniker allows for arbitrary monikercreation. A macro moniker contains a macro script that controls thereduction of a macro moniker to another moniker. During reduction, thescript is parsed and processed by the method Reduce. One skilled in theart would appreciate that parsing and processing macro scripts are wellknown. The result of the processing is another moniker that is returnedas the reduced moniker. For example, Code Table 5 contains a script thatdirects the macro moniker to reduce to a moniker referencing thedirectory “c:\reports\expenses\weekly\user\dayofweek”, where user is thecurrent user name (e.g., “Smith”) and dayofweek is the day of week ofyesterday (e.g., “Thursday”). The macro moniker with the script of CodeTable 5 may reduce to a file moniker with a path name of“c:\reports\expenses\weekly\smith\thursday”. The macro moniker maycontain a pointer to the reduced moniker. The method BindToObject of amacro moniker would typically invoke the method Reduce and then invokethe method BindToObject of the reduced moniker. Code Table 6 contains amacro script that directs the macro moniker to reduce to a moniker andin the process prompts the user for a portion of the path. CODE TABLE 7{ SELECT FIRST printer.name FROM CampusPrinter WHERE (printerType = =PostScript OR printerType = = PCL) AND printerLocation INCLUDES“Building 1” ORDER BY printQueueLength }

In a preferred embodiment, a query moniker allows for arbitraryreduction to a moniker identified by a query. A query moniker contains aquery that controls the reduction. The query is evaluated to produce afile moniker that satisfies the query. For example, Code Table 7contains a query (in a structured query language) that may reduce to thefile moniker with path name “\\printserver10\printer2”. The queryevaluates to a list of printers that can accommodate either PostScriptor PCL documents and that is in a certain building. The list is sortedby the length of the print queue, and the printer with the shortestprint queue is selected.

IMoniker::IsEqual

HRESULT IMoniker::IsEqual(pmkOtherMoniker)

This method determines whether this moniker and the specified othermoniker (pmkOtherMoniker) reference the same object. This method is usedin a preferred implementation of a running object table. The followingtable describes the parameters of the method IsEqual: Argument TypeDescription pmkOtherMoniker IMoniker* the other moniker with whom thismoniker is compared. return value HRESULT S_OK, S_FALSE

FIG. 25 is a flow diagram of the method IsEqual of the classCFileMoniker. In step 2501, if the other moniker (pmkOtherMoniker) is afile moniker, then the method continues at step 2502, else the monikersare not equal and the method returns a false. In step 2502, if the countof anti-monikers for this moniker (m_cAnti) is equal to the count ofanti-monikers for the other moniker, then the method continues at step2503, else the monikers are not equal and the method returns a false. Instep 2503, if the path for this moniker (m_lpszPath) is equal to thepath for the other moniker, then the method returns indicating that themonikers are equal, else the method returns indicating that the monikersare not equal.

FIG. 26 is a flow diagram of the method IsEqual of the classCCompositeMoniker. In step 2601, if the other moniker is a compositemoniker, then the method continues at step 2602, the method returnsindicating that the monikers are not equal. In step 2602, if the leftmoniker of this moniker (m_pmkLeft) is equal to the left moniker of theother moniker, then the method continues at step 2603, else the methodreturns an indication that the monikers are not equal. In step 2603, ifthe right moniker of this moniker (m_pmkRight) is equal the rightmoniker of the other moniker, then the method returns an indication thatthe monikers are equal, else the method returns an indication that themonikers are not equal. In an alternate embodiment of the methodIsEqual, the method checks each component moniker of this moniker andthe other moniker to determine if the monikers are equal.

IMoniker::Hash

HRESULT IMoniker::Hash(pdwHash)

This method returns a 32-bit integer associated with this moniker. Thisinteger is used for maintaining tables of monikers: the moniker can behashed to determine a hash bucket in the table, then compared with themethod IsEqual against all the monikers presently in that hash bucket.Two monikers that compare as equal have the same hash value. Thefollowing table describes the parameters of the method Hash: ArgumentType Description pdwHash DWORD * the place in which to put the returnedhash value. return value HRESULT S_OK

FIG. 27 is a flow diagram of the method Hash of the classCCompositeMoniker. In step 2701, the method invokes the method Hash ofthe left moniker. In step 2702, the method invokes the method hash ofthe right component moniker. In step 2703, the method generates theexclusive-or of the left hash value and the right hash value and returnsthat as the hash value of the method. The method Hash of the classCItemMoniker performs a hash function on the item name and returns thevalue.

IMoniker::Inverse

HRESULT IMoniker::Inverse(ppmk)

The method Inverse returns a moniker that when composed onto the end ofthis moniker or one of similar structure annihilates it; that is,composes to NULL. The method Inverse is an abstract generalization ofthe “..” operation in traditional file systems. For example, a filemoniker that represents the path “a\b\c\d” has as its inverse a monikercontaining the path “..\..\..\..”, since “a\b\c\d” composed with“..\..\..\..” yields nothing. The inverse of a moniker does notannihilate just that particular moniker, but all monikers with a similarstructure. Thus, the inverse of a generic composite moniker is thereverse composite of the inverse of its component monikers. Certainclasses of monikers may have trivial inverses. If a moniker adds onemore component moniker to an existing structure; its inverse is amoniker that removes the last component of the existing structure. Amoniker that when composed onto the end of a moniker removes the lastcomponent is referred to as anti moniker. One skilled in the art wouldappreciate that not all monikers have inverses. The inverse of an antimoniker, for example, does not exist. The following table describes theparameters of the method Inverse. Argument Type Description ppmkIMoniker** the place to return the inverse moniker. return value HRESULTS_OK, MK_E_NOINVERSE.

An anti moniker is a moniker that when composed onto the end of ageneric composite moniker removes the last component moniker. Composingan anti moniker onto the end of another kind of moniker preferablyannihilates the other moniker. The class CAntiMoniker contains a datamember that is a count of the number of anti monikers (m_cAnti).Whenever an anti moniker is composed with another anti moniker, theresulting composition is an anti moniker with its count equal to the sumof the counts of the composed anti monikers.

FIGS. 28A, 28B, and 28C are block diagrams illustrating composition withinverse monikers. In FIG. 28A, an item moniker 2801 is composed withanti moniker 2802 which results in annihilation of the monikers. In FIG.28B, the generic composite moniker 2803 which comprises componentmoniker 2804 and 2801 is composed with anti moniker 2802. Since antimoniker 2802 is the inverse of item moniker 2801, the item moniker 2801and the anti moniker 2802 is annihilated. The result of the compositionis file moniker 2805. In FIG. 28C, generic composite moniker 2806 iscomposed with generic composite moniker 2807 resulting in annihilationof generic composition monikers 2806 and 2807. Generic composite moniker2806 comprises file moniker 2804 and item moniker 2801. Genericcomposite moniker 2807 comprises anti moniker 2802 and file moniker2808. The anti moniker 2802 is the inverse of item moniker 2801, andfile moniker 2808 is the inverse of file moniker 2804.

FIG. 29 is a flow diagram of the method Inverse of the classCCompositeMoniker. In step 2901, the method invokes the method Inverseof the left moniker of this moniker to retrieve its inverse moniker. Instep 2902, the method invokes the method Inverse of the right moniker ofthis moniker to retrieve its inverse moniker. In step 2903, the methodinvokes the function CreateGenericComposite passing it the right inverseand the left inverse and returns. The left inverse moniker is composedonto the end of the right inverse moniker so that during composition theright moniker will compose with the right inverse and the left monikerwill compose with the left inverse moniker resulting in annihilation.

FIG. 30 is a flow diagram of the method Inverse of the classCItemMoniker. Since the inverse of an item moniker is an anti moniker,the method creates an instance of an anti moniker and returns it.

FIG. 31 is a flow diagram of the method ComposeWith of the classCItemMoniker. This method illustrates the annihilation of monikers. Instep 3101, if the moniker on the right to be composed with is an antimoniker, then the method continues at step 3102, else the methodcontinues at step 3103. In step 3102, the method invokes the methodAnnihilateOne of the anti moniker and returns the result as thecomposite moniker. Consequently, an item moniker that is composed withan anti moniker with a count greater than one results in an antimoniker. In step 3103, if the caller wants a generic compositionreturned (fOnlyIfNotGeneric==FALSE), then the method continues at step3104, else the method returns an indicator that a generic compositemoniker is needed. In step 3104, the method invokes the functionCreateGenericComposite passing this moniker and the right moniker andreturns with the composite moniker.

FIG. 32 is a flow diagram of the method AnnihilateOne of the classCAntiMoniker. This method annihilates one of the counts of this moniker.In step 3201, if the count of the anti moniker is equal to one, then themethod continues at step 3202, else the method continues at step 3203.In step 3202, the method sets the moniker to return to NULL and returns.In step 3203, the method creates a new anti moniker and sets its countto the count of this moniker minus one and returns that newly-createdmoniker.

FIG. 33 is flow diagram of the method ComposeWith of the classCAntiMoniker. In step 3301, if the right moniker (pmkRight) is an antimoniker, then the method continues at step 3302, else the methodcontinues at step 3304. In step 3302, the method calculates the sum ofthe count of this moniker and the count of the right moniker. In step3303, the method creates an anti moniker and sets its count to the sumand returns it as the composite moniker. In step 3304, if the callerwants a generic composition, then the method continues at step 3305,else the method returns an indication that a generic composition isneeded. In step 3305, the method invokes a functionCreateGenericComposite passing it this moniker and the right moniker andreturns the composite.

IMoniker::CommonPrefixWith

HRESULT IMoniker::CommonPrefixWith(pmkOther, ppmkPrefix)

This method determines the longest common prefix that this monikershares with the other moniker (pmkOther). The following table describesthe parameters of the method CommonPrefixWith. Argument Type DescriptionpmkOther IMoniker* the moniker with whom the common prefix is to bedetermined. ppmkPrefix IMoniker* the place to return the common prefixmoniker. NULL is returned only in the case that the common prefix doesnot exist. return value HRESULT MK_S_ME, indicating that this moniker isthe common prefix. MK_S_HIM, indicating that the other moniker(pmkOther) is the common prefix. MK_S_US, indicating that the twomonikers are equal. S_OK, indicating that the common prefix exists butis neither this moniker nor the other moniker. MK_S_NOPREFIX indicatingthat no common prefix exists.

FIG. 34 is a block diagram illustrating a common prefix of genericcomposite monikers. The generic composite moniker 3401 and 3402represent generic composite monikers for whom a common prefix is to bedetermined. Generic composite moniker 3401 includes component itemmonikers A, B, C, and D. Generic composite moniker 3402 comprisescomponent item monikers A, B, and D. The resulting moniker is a genericcomposite moniker 3403 with a component moniker for Item A and acomponent moniker for Item B. The common prefix of (A∘B∘C∘D) and (A∘B∘D)is (A∘B).

FIG. 35 is a flow diagram of the method CommonPrefixWith of the classCCompositeMoniker. In step 3501, if the other moniker (pmkOther) is ageneric composite moniker, then the method continues at step 3505, elsethe method continues at step 3502. In step 3502, the method invokes themethod CommonPrefixWith of the first component moniker of this monikerpassing the other moniker and returning the common prefix. In step 3503,if the first component moniker of this component moniker is a commonprefix with the other moniker, then the method returns an indicationthat a common prefix exists but neither this moniker nor the othermoniker is the common prefix, else the method continues at step 3504. Instep 3504, if the method returns an indication that the first componentmoniker of this moniker and the other moniker are common prefixes, thenthe method returns an indication that the other moniker is a commonprefix of this moniker, else the method returns with the indicationreturned in step 3502. In step 3505, the method invokes the methodCommonPrefixWith for the first component moniker of this moniker passingthe first component moniker of the other moniker and returning theresult. If the first component moniker of this moniker and the firstcomponent moniker of the other moniker are common prefixes of eachother, then the method continues at step 3507, else the method continuesat step 3509. In step 3507, the method invokes the methodCommonPrefixWith for a moniker comprising all but the first componentmoniker of this moniker and passing it all but the first componentmoniker of the other moniker. This recursively invokes the methodCommonPrefixWith to determine the extent of the common prefix. In step3508, the method composes the result of step 3505 and step 3507 andreturns. In step 3509, if the first component moniker of the othermoniker is a prefix of the first component moniker of this moniker, thenthe method continues at step 3510, else the method continues at step3511. In step 3510, the method indicates that the prefix is the firstcomponent moniker of the other moniker and returns. In step 3511, if thefirst component moniker of this moniker is the prefix of the firstcomponent moniker of the other moniker, then the method continues atstep 3512, else the method returns the result that was returned in step3505. In step 3511, the method sets the prefix to return to this monikerand returns.

FIG. 36 is a flow diagram of the method CommonPrefixWith of the classCFileMoniker. The method scans the path names of this moniker and theother moniker to determine the common prefix. The count of anti monikersis assumed to precede the path names. In step 3601, if the other moniker(pmkOther) is a file moniker, then the method continues at step 3603,else the method continues at step 3602. In step 3602, the method invokesthe function MonikerCommonPrefix (described below) and returns. In step3603, if the count of anti monikers for this moniker (m_cAnti) is notequal to the count of anti monikers for the other moniker, then themethod continues at step 3606, else the method continues at step 3604.In step 3604, the method scans the file path of the other moniker(m_lpszPath) and the file path of this moniker to determine the commonprefix. In step 3605, the method sets the result and returns. In step3606, the method determines the minimum of the anti moniker count ofthis moniker and the anti moniker count of the other moniker. In step3607, the method creates a file moniker as the prefix moniker to return.In step 3608, the method sets the count of the anti monikers of theprefix to the minimum count of anti monikers. In step 3609, if theminimum count of anti monikers is in this moniker, then the methodcontinues at step 3611, else the method continues at step 3610. In step3610, if the path of the other moniker is NULL, then the method returnsan indication that the other moniker is a common prefix, else the methodreturns an indication that neither moniker is the common prefix. In step3611, if the path of this moniker is NULL, then the method returnsindicating that this moniker is a common prefix, else the method returnsindicating that neither moniker is the common prefix.

FIG. 37 is a flow diagram of the method CommonPrefixWith of the classCItemMoniker. In step 3701, if this moniker is equal to the othermoniker, then the method continues at step 3702, else the method returnsan indication that there is no prefix in common. In step 3702, themethod sets the prefix moniker equal to this moniker and returns anindication that both monikers are common prefixes.

FIG. 38 is a flow diagram of the method CommonPrefixWith of the classCAntiMoniker. In step 3801, if the other moniker is an anti moniker,then the method continues at step 3803, else the method continues atstep 3802. In step 3802, the method invokes the functionMonikerCommonPrefix and returns. If the count of this moniker is lessthan or equal to the count of the other moniker, then the methodcontinues at step 3805, else the method continues at step 3804. In step3804, the method sets the prefix moniker to point to the other monikerand returns an indication that the other moniker is the common prefix.In step 3805, the method sets the prefix moniker equal to this moniker.In step 3806, if the count of this moniker is equal to the count of theother moniker, then the method returns an indication that both monikersare common prefixes, else the method returns an indication that thismoniker is a common prefix.

MonikerCommonPrefixWith

HRESULT MonikerCommonPrefixWith(pmkThis, pmkOther, ppmkPrefix

This function is invoked by implementations of the methodCommonPrefixWith. This function handles the situation when theimplementation does not recognize the type of the other moniker. Thefollowing table describes the parameters of the functionMonikerCommonPrefixWith: Argument Type Description pmkThis IMoniker *one moniker for the computation of the common prefix. pmkOtherIMoniker * the other moniker for the computation of the common prefix.ppmkPrefix IMoniker ** pointer to the common prefix. return valueHRESULT S_OK, MK_S_HIM, MK_S_ME, MK_S_US, MK_S_NOPREFIX

FIG. 39 is a flow diagram of the function MonikerCommonPrefixWith. Instep 3901, if this moniker (pmkThis) is a generic composite moniker,then the method continues at step 3902, else the method continues atstep 3903. In step 3902, the method invokes the method CommonPrefixWithof this moniker passing it the other moniker (pmkOther) and returns. Instep 3903, if the other moniker is a generic composite, then the methodcontinues at step 3905, else the method continues at step 3904. In step3904, if neither moniker is a generic composite moniker, then the methodsets the prefix to NULL and returns an indication that there is noprefix in common. In step 3905, the method invokes the methodCommonPrefixWith of the other moniker passing this moniker. In step3906, if this moniker is the common prefix, then the method returns withan indication, else the method continues at step 3907. In step 3907, ifthe other Moniker is the common prefix, then the method returns with anindication, else the method returns with the indication returned in3905.

IMoniker::RelativePathTo

HRESULT IMoniker::RelativePathTo(pmkOther, ppmkRelPath)

This method returns as a moniker that when composed onto the end of thismoniker or one with a similar structure yields the other moniker(pmkOther). Implementations of this method preferably determine thelongest prefix that this moniker and the other moniker have in common.This separates this moniker and the other into two parts, say(P,T_(this)) and (P,T_(other)) respectively, where P is the commonprefix. T_(this) and T_(other) represent the trailing components. Therelative path result is then T⁻¹ _(this)∘T_(other), where T⁻¹ indicatesthe inverse. Thus, (P,T_(this))∘(T⁻¹ _(this)∘T_(other))=(P, T_(other)).Argument Type Description pmkOther IMoniker* the other moniker to whicha relative path should be taken. ppmkRelPath IMoniker* May not be NULL.The place at which the relative path is returned. return value HRESULTMK_S_HIM, indicating that the only form of relative path is in fact justthe other moniker (pmkOther). S_OK, indicating that a non-trivialrelative path exists.

FIG. 40 is a block diagram illustrating a relative path to moniker. Whengeneric composite moniker 4001 is composed with relative path to moniker4002, the result is generic composite moniker 4003. During composition,the component moniker Item C of generic composite moniker 4001 and theanti moniker of generic composite moniker 4002 annihilate. The genericcomposite moniker 4002 is the relative path to moniker to go from thecomposite generic moniker 4001 to 4003. More precisely, the relativepath to moniker is the inverse of the portion that is not the commonprefix of generic composite monikers 4001 and 4003 composed with theportion of generic composite moniker 4003 that is not the common prefix.

FIGS. 41A and 41B are block diagrams illustrating a usage of the methodRelativePathTo. The document 4101 has a path name of“c:\reports\monthly\june.doc”. The document 4101 contains a link to arange within the spreadsheet document 4102. The spreadsheet document hasthe path “c:\reports\monthly\data\june.xls”. The range is identified by“R4C7:R8C12”. The document 4101 preferably stores a moniker indicatingthe absolute path name of the range and the relative path name of therange. In this way, when the document 4101 is moved to a new directorywith a similar structure, the correct range can be retrieved from thatdirectory structure using the relative path. FIG. 41B illustrates ageneric composite moniker 4103 describing the absolute path to thespreadsheet range. The generic composite moniker 4103 includes a filemoniker 4104 with the absolute path name of the spreadsheet file and anitem moniker 4105 which describes the spreadsheet range. The relativepath to moniker is generic composite moniker 4106. Generic compositemoniker 4106 includes file monikers 4107 and 4108, and item moniker4109. The generic composite moniker 4106 is the relative path to monikerfor the absolute path name of the document 4101. When the moniker forthe absolute path name of the document 4101 is composed with the genericcomposite moniker 4106, the result is the proper composite monikerneeded to access the spreadsheet file.

FIGS. 42A, 42B, and 42C comprise a flow diagram of the methodRelativePathTo of the class CCompositeMoniker. In step 4201, if theother moniker (pmkOther) is a generic composite moniker, then the methodcontinues at step 4202, else the method continues at step 4227. In step4202 through 4207, the method loops determining the common prefix ofthis moniker and the other moniker. In step 4202, the method sets avariable nCount equal to 0. The variable nCount keeps track of thenumber of component monikers in the common prefix. In step 4203, themethod selects the next component moniker of the other moniker, startingwith the first. The enumeration of generic composite monikers isdescribed below. In step 4204, the method selects the next componentmoniker of this moniker, starting with the first. In step 4205, if acomponent moniker of the other moniker and a component moniker of thismoniker are selected, then the method continues at step 4206, else themethod continues at step 4208. In step 4206, if the selected componentmonikers are equal, then the method continues at step 4207, else themethod continues at step 4208. In step 4207, the method increments thevariable nCount and loops to step 4203 to select the next componentmonikers. In step 4208, if the variable nCount equals 0, then thismoniker and the other moniker have no common prefix and the methodcontinues at step 4209, else the method continues at step 4214. In step4209, the method invokes the method RelativePathTo of the firstcomponent moniker of this moniker passing it the first component monikerof the other moniker and indicating to return the result as the inverseof the first component of this moniker. In step 4210, if the invocationof the method RelativePathTo in step 4209 indicates that a non-trivialrelative path exists, then the method continues at step 4211, else themethod continues at step 4213. In step 4211, the method indicates thatthe first component moniker of this moniker is equal to the result ofstep 4209. In step 4212, the method selects the next component monikerof the other moniker and continues at step 4216. In step 4213, themethod sets the relative path to point to the other moniker and returnsan indication that the relative path is the other moniker. In step 4214,if not all the component monikers of the this moniker have beenselected, then the method continues at step 4215, else the methodcontinues at step 4216. In step 4215, the method determines the inverseof the selected component moniker of this moniker and continues at step4216. In step 4216, if the selected component moniker of this moniker isnot equal to NULL, then the method continues at step 4217, else themethod continues at step 4221. In step 4217, the method determines theinverse of the component monikers of this moniker that have not beenselected. In step 4218, if the inverse is not NULL, then the methodcontinues at step 4219, else the method continues at step 4220. In step4219, the method invokes the method ComposeWith of the inverse passingit the inverse of the last selected component moniker of this moniker tocreate an inverse for the tale portion of this moniker and the methodcontinues at step 4221. In step 4220, the method sets the inverse of thetale portion of this moniker equal to the inverse of the last selectedcomponent moniker of this moniker and continues at step 4221. In step4221, if the selected component moniker of the other moniker is notequal to NULL, then the method continues at step 4223, else the methodcontinues at 4222. In step 4222, the method sets the tale of the othermoniker equal to NULL and continues at step 4224. In step 4223, themethod composes the selected component moniker of the other moniker withtale of the other moniker and continues at step 4224. In step 4224, ifthe inverse of the tale of this moniker is not equal to NULL, then themethod continues at step 4226, else the method continues at step 4225.In step 4225, the method sets the relative path to the tale of the othermoniker and returns. In step 4226, the method composes with the inverseof the tale of this moniker with the tale of the other moniker andreturns that as a relative path. In step 4227, the method selects thenext component moniker of this moniker. In step 4228, if the selectedcomponent moniker of this moniker is equal to the other moniker, thenthe method continues at step 4229, else the method continues at step4230. In step 4229, the method gets the inverse of this moniker andreturns it as the relative moniker. In step 4230, the method invokes amethod RelativePathTo of the selected component moniker of this monikerpassing it the other moniker. In step 4232, if the method invoked instep 4230 indicates that the other moniker is the relative path tomoniker, then the method continues at step 4232, else the methodcontinues at step 4233. In step 4232, the method sets the relative pathto moniker to point to the other moniker and returns. In step 4233, themethod gets the inverse of the tale of this moniker. In step 4234, themethod composes with the inverse of the tale of this moniker with therelative path to moniker returned in step 4230 and returns.

MonikerRelativePathTo

HRESULT MonikerRelativePathTo(pmkSrc, pmkDest, ppmkRelPath, reserved)

This function is invoked by implementations of the methodRelativePathTo. This method handles the situation when theimplementation does not recognize the type of the other moniker.Argument Type Description pmkSrc IMoniker * the starting moniker for thecomputation of the relative path. pmkDest IMoniker * the moniker towhich a relative path should be taken. ppmkRelPath IMoniker ** May notbe NULL. The place at which the moniker of pmkDest relative to pmkSrc isto be returned. reserved BOOL must be non-zero return value HRESULTS_OK, MK_S_HIM

FIG. 43 is a flow diagram of the function MonikerRelativePathTo. In step4301 if the source moniker or the destination moniker is a genericcomposite moniker, then the method continues at step 4304, else themethod continues at step 4302. In step 4302, if the parameterfCalledFromMethod is true, then the method continues at step 4303, elsethe method continues at step 4305. In step 4303, the method sets therelative path to the destination moniker and returns an indicationmoniker that the destination moniker is the relative path to. In step4304, if the source moniker is a generic composite moniker, then themethod continues at step 4305, else the method continues at step 4306.In step 4305, the method invokes the method RelativePathTo of the sourcemoniker passing the destination moniker and returns the relative pathfrom that invocation. In step 4306, if the source moniker is equal tothe first component moniker of the destination moniker, then the methodcontinues at step 4307, else the method continues at step 4308. In step4307, the method sets the relative path to moniker equal to a monikercomprising all but the first component moniker of the destinationmoniker and returns. In step 4308, the method invokes the methodRelativePathTo of the source moniker passing the first component monikerof the destination moniker. In step 4309, if no error is returned, thenthe method continues at step 4310, else the method continues at step4311. In step 4310, the method invokes the functionCreateGenericComposite passing the relative path to moniker returned instep 4308 and a moniker comprising all but the first component monikerof the destination moniker and returns. In step 4311, the method setsthe relative path to moniker equal to the destination moniker andreturns an indication that the destination moniker a relative path tomoniker.

IMoniker::Enum

HRESULT IMoniker::Enum(fForward, ppenmMoniker)

This method returns an interface that permits the enumeration of thecomponent monikers of which this moniker is logically a composite. For ageneric composite moniker, this enumerates the components of which thecomposite is composed. For other monikers, the semantics of thecomponents of which it is a composite are implementation-defined. Forexample, enumerating the components of a file moniker returns eachportion of the internally stored path name, even though they are notstored internally as actual separate monikers. Monikers that have nodiscernible internal structure return NULL instead of an enumerator.

The IEnumMoniker interface is an enumerator that supports theenumeration of items which are monikers. interface IEnumMoniker :IUnknown { virtual HRESULT Next(ULONG celt, IMoniker* rgelt[ ], ULONG*pceltFetched) = 0; virtual HRESULT Skip(ULONG celt) = 0; virtual HRESULTReset( ) = 0: virtual HRESULT Clone(IEnumMoniker** ppenm) = 0; };

The following table describes the parameters of the method Enum:Argument Type Description fForward BOOL If true, then the enumerationshould be done in the normal order. If false, then the order should bethe reverse of the order enumerated by the normal order. ppenmMonikerIEnumMoniker** On exit, the returned enumerator. May be NULL, signifyingthat there is nothing to enumerate. return value HRESULT S_OK.

CODE TABLE 8 class CCompositeMonikerEnum: IEnum { CCompositeMonikerFAR * m_pcm; BOOL m_fForward; se m_pBase; se m_pTop; LPMONIKER m_pNext;}

FIG. 44 is a flow diagram of the method Enum of the classCCompositeMoniker. In step 4401, the method instantiates an enumeratorobject of type CCompositeMonikerEnum for this composite object. CodeTable 44 illustrates the data members of a class definition for theenumerator. The object contains a pointer to the moniker beingenumerated (m_pCM), a flag indicating whether the enumeration is in theforward direction (m_fForward), pointers indicating the base and the topof a stack (m_pBase, m_pTop), and a pointer to the next componentmoniker to be returned (m_pNext). In steps 4402 through 4406, the methodinitializes the data members of the instantiated object. In step 4406,the method invokes the method GetNext passing this moniker and sets datamember m_pNext to the result.

FIG. 45 is a flow diagram of the private method GetNext of the classCCompositeMonikerEnum. The enumeration of a composite moniker is aleft-to-right, depth-first traversal of the tree formed by the compositemoniker. The enumerator maintains a stack to track the traversal of thetree. In step 4501, the method sets a pointer to a rover (pmkRover)equal to the passed moniker. The rover pointer is used to traverse thetree. In step 4502, if the passed moniker is NULL, then the methodreturns NULL, else the method continues at step 4503. In step 4503, ifthe moniker pointed to by the rover is a generic composite moniker, thenthe method continues at step 4504, else a component moniker is locatedand the method returns the moniker pointed to by the rover. In step4504, the method invokes the method Push to push the generic compositemoniker indicated by the rover onto the stack. In step 4505, if theenumeration is being performed in the forward direction, the methodcontinues at step 4506, else the method continues at step 4507. In step4506, the method sets the rover to point to the left moniker of themoniker pointed to by the rover and loops to step 4503. In step 4507,the method sets the rover to point to the right moniker of the monikerpointed to by the rover and loops to step 4503.

FIG. 46 is a flow diagram of the method Next of the classCCompositeMonikerEnum. Each time this method is invoked it returns thenext component moniker of the composite moniker. The method Next returnsan array of component monikers up to a maximum number specified as aparameter. In step 4601, the method initializes a count variable to 0.In step 4602, if the count is less than the requested count of componentmonikers and not all the component monikers have been returned, then themethod continues at step 4603, else the method continues at 4607. Instep 4603, the method stores the next component moniker in the returnarray. In steps 4604 and 4605, the method increments the count and indexinto the return array. In step 4606, the method sets the next componentmoniker to point to the moniker returned by the method Pop and loops tostep 4602. In step 4607, if a pointer to the count of fetched elementsis not equal to NULL, then the method sets the pointer equal to thecount in step 4608. The method then returns.

The methods Push and Pop of the class CCompositeMonikerEnum implement astack. The method Push pushes the passed generic composite moniker ontoa stack. The method Pop removes a top generic composite moniker from thestack and invokes the method GetNext passing it the right moniker if asearch is being performed in the forward direction and a left moniker ifthe search is being performed in the reverse direction. The method Popreturns the component moniker returned by the method GetNext.

Pointer Moniker Class

In a preferred embodiment, a pointer moniker is a class of moniker thatwraps an existing pointer to an object in a moniker so that it mayparticipate as a component moniker in the moniker binding process. Apointer is a reference into “active space,” that is, memory of aprocess. A moniker typically is a reference into “passive space,” thatis, the representation of an object on disk. Pointer monikers provide ameans by which a given use of a moniker can transparently referenceeither active or passive space.

In a preferred embodiment, the method BindToObject of a pointer monikerinvokes the method QueryInterface of the pointed to object. The methodBindToStorage returns MK_E_NOSTORAGE. The method Reduce reduces themoniker to itself. The method ComposeWith does a generic composition.The method Enum returns NULL. The method IsSystemMoniker returnsMKSYS_NONE. The method IsEqual uses the identity test paradigm onpointers after first checking that the other moniker for the rightclass. The method Hash returns a constant. The methodGetTimeOfLastChange returns MK_E_UNAVAILABLE. The method Inverse returnsan anti moniker. The method RelativePathTo returns the other moniker.The method GetDisplayName returns NULL. The method ParseDisplayNamebinds to the punk pointer using IParseDisplayName interface. Pointermonikers do not serialize; that is, the Save of the IPersistStreaminterface returns an error.

CreatePointerMoniker

HRESULT CreatePointerMoniker(punk, ppmk)

This function wraps a pointer in a pointer moniker so that it can bepresented to interfaces that require monikers for generality, butspecific uses of which can usefully deal with a moniker which cannot besaved to backing store. The following table describes the parameters ofthe method CreatePointerMoniker. Argument Type Description punkIUnknown* the pointer that we are wrapping up in a moniker. ppmkIMoniker** the returned Pointer Moniker. return value HRESULT S_OK,E_OUTOFMEMORY

FIG. 47 is a flow diagram of the method Create of the classCPointerMoniker. In step 4701, the method instantiates a new pointermoniker. In step 4702, the method sets a data member (m_Punk) the newpointer moniker to point to the passed object and returns.

FIG. 48 is a flow diagram of the method BindToObject of the classCPointerMoniker. In step 4801, the method invokes the methodQueryInterface of the pointed to object passing the identifier of therequested interface. The method then returns with the requestedinterface.

FIG. 49 is a diagram illustrating a pointer moniker. Object 4901 iswrapped in pointer moniker 4902. Pointer moniker 4902 contains a pointerto the object 4901.

Although the present invention has been described in terms of preferredembodiments, it is not intended that the invention be limited to theseembodiments. Modifications within the spirit of the invention will beapparent to those skilled in the art. The scope of the present inventionis defined by the claims which follow.

1.-13. (canceled)
 14. A computer-readable medium storingcomputer-executable instructions for causing a computer programmedthereby to perform a method of evaluating a moniker object, the methodcomprising: receiving an invocation of a hashing function member of afirst moniker object, the first moniker object including naminginformation for source data; and returning a hash value for the firstmoniker object.
 15. The computer-readable medium of claim 14, whereinthe method further comprises for each of one or more other monikerobjects having the hash value, receiving an invocation a comparisonfunction member of the first moniker object, wherein the invocationincludes passing a reference to the other moniker object; and returningan indicator whether the first moniker object is equal to the othermoniker object.
 16. The computer-readable medium of claim 15 wherein arunning object table includes an entry for each of the one or more othermoniker objects.
 17. The computer-readable medium of claim 15, whereinthe method further comprises: if none of one or more other monikerobjects have the hash value, returning an indicator that the firstmoniker object is equal to none of the one or more other monikerobjects.
 18. A computer-readable medium storing computer-executableinstructions for causing a computer programmed thereby to perform amethod of providing a client with access to a resource identified by aserver moniker object, the server moniker object having stateinformation identifying the resource, the method comprising: undercontrol of a client, receiving from a server an indication ofunmarshalling code and state information for use by the unmarshallingcode, the state information identifying a resource; and executing theunmarshalling code to instantiate a client moniker object as a proxy forthe server moniker object, the client moniker object including the stateinformation.
 19. The computer-readable medium of claim 18 wherein themethod further comprises: binding to the resource by invoking bindingcode of the client moniker object, wherein the binding code uses thestate information to bind to the resource without accessing a servermoniker object.
 20. The computer-readable medium of claim 18 wherein thestate information is immutable.
 21. A computer-readable medium storingcomputer-executable instructions for causing a computer programmedthereby to perform a method of providing a client with access to aresource identified by a server moniker object, the server monikerobject having state information identifying the resource, the methodcomprising: receiving an indication of unmarshalling code and stateinformation for use by the unmarshalling code, the state informationidentifying a resource; and passing the indication of the unmarshallingcode and the state information to the client for use in instantiating aclient moniker object as a proxy for the server moniker object, theclient moniker object including the state information.
 22. Thecomputer-readable medium of claim 21 wherein the receiving theindication of unmarshalling code comprises getting class identifyinginformation for the proxy.
 23. The computer-readable medium of claim 21wherein the passing comprises passing class identifying information forthe proxy and a marshalling packet to the client.
 24. Thecomputer-readable medium of claim 23 wherein the method furthercomprises: creating the marshalling packet; and buffering in themarshalling packet information used in instantiating the client monikerobject as the proxy for the server moniker object.
 25. Thecomputer-readable medium of claim 21 wherein the state information isimmutable.